import traceback
from flask import Blueprint, current_app, request, jsonify
from flask_caching import Cache
import akshare as ak
import math
from app.models import db, User, Transaction, UserAsset, AssetTypeEnum, Preference, UserBehaviorStats
from datetime import datetime

stock_controller = Blueprint('stock_controller', __name__)
cache = Cache(config={'CACHE_TYPE': 'simple'})

@stock_controller.before_app_request
def init_cache():
    cache.init_app(current_app)

@stock_controller.before_request
def log_request():
    current_app.logger.info(f"[STOCK] {request.method} {request.url}")



@stock_controller.get('/info')
def get_info():
    """
    GET /stock/info?symbol=sh600000
    返回该股票的个股静态信息列表 [{item, value}, …]
    """
    symbol = request.args.get('symbol', '').strip()
    if not symbol:
        return jsonify({'code': 400, 'msg': 'symbol 参数必填'}), 400

    # 支持前缀 sh/ sz
    code = symbol[-6:]
    cache_key = f"stock_info:{code}"
    data = cache.get(cache_key)
    if data:
        return jsonify({'code': 0, 'data': data})

    try:
        # 拉取数据
        df = ak.stock_individual_info_em(symbol=code)

        # 打印实际拿到的列，确认结构
        # current_app.logger.debug(f"[STOCK] raw columns = {df.columns.tolist()}")

        # 直接转 records
        records = df.to_dict(orient='records')

        cache.set(cache_key, records, timeout=300)
        return jsonify({'code': 0, 'data': records})

    except Exception as e:
        # 打完整 traceback 到日志
        # current_app.logger.error("[STOCK] 获取个股信息失败：\n" + traceback.format_exc())
        # 并把异常消息返给前端
        return jsonify({'code': 500, 'msg': str(e)}), 500

@stock_controller.get('/list')
def get_list():
    """
    GET /stock/list
    返回沪深A股当前所有个股行情，字段包括：
      code, name, latest, change, change_rate, volume, amount, turnover_rate, amplitude,
      high, low, open, prev_close, volume_rate, pe, pb
    """
    cache_key = 'stock:list'
    data = cache.get(cache_key)
    if data:
        # current_app.logger.debug(f"[STOCK] CACHE HIT {cache_key}")
        return jsonify({'code': 0, 'data': data})

    try:
        # 调用 akshare 获取所有A股现价
        df =  ak.stock_sh_a_spot_em()
        # 重命名并选取需要的列
        df = df.rename(columns={
            '序号': 'index',
            '代码': 'symbol',
            '名称': 'name',
            '最新价': 'price',
            '涨跌幅': 'change_rate',
            '涨跌额': 'change',
            '成交量': 'volume',       # 单位：手
            '成交额': 'amount',       # 单位：元
            '换手率': 'turnover_rate',
            '振幅': 'amplitude',
            '最高': 'high',
            '最低': 'low',
            '今开': 'open',
            '昨收': 'prev_close',
            '量比': 'volume_rate',
            '市盈率-动态': 'pe',
            '市净率': 'pb',
            "总市值": "market_cap",
            "流通市值": "circulating_cap",
            "涨速": "speed",
        })
        # 只保留以上列，防止字段过多
        cols = ['index','symbol', 'name', 'price', 'change', 'change_rate',
                'volume', 'amount', 'amplitude',
                'high', 'low', 'open', 'prev_close', 'volume_rate', 'pe','pb','market_cap','circulating_cap','speed','turnover_rate']
        df = df[cols]

        # 转成 records
        records = df.to_dict(orient='records')
        # 缓存 50 秒
        cache.set(cache_key, records, timeout=50)


        
        for rec in records:
            for k,v in rec.items():
                if isinstance(v, float) and math.isnan(v):
                    rec[k] = None


        return jsonify({'code': 0, 'data': records}),200

    except Exception as e:
        current_app.logger.error(f"[STOCK] get_list error:\n{traceback.format_exc()}")
        return jsonify({'code': 500, 'msg': str(e)}), 500



#  分时数据接口
@stock_controller.get('/a_minute')
def get_a_minute():
    """
    GET /stock/a_minute?symbol=sh900901&period=1&adjust=qfq
    返回该 A 股或指数分时数据，支持 period=1,5,15,30,60，adjust 可选 "", "qfq", "hfq"
    """
    symbol = request.args.get('symbol', '').strip()
    period = request.args.get('period', '1').strip()

    # 确保 symbol 带有 "sh" 前缀
    if not symbol.startswith('sh'):
        symbol = f"sh{symbol}"


    if not symbol:
        return jsonify({'code': 400, 'msg': 'symbol 参数必填'}), 400

    cache_key = f"stock_a_minute:{symbol}:{period}"
    data = cache.get(cache_key)
    if data:
        return jsonify({'code': 0, 'data': data})

    try:
        # 调用 akshare 接口
        df = ak.stock_zh_a_minute(symbol=symbol, period=period)
        # 为 ECharts 准备：把 "day" 列格式化成字符串
        df = df.rename(columns={'day': 'time'})
        records = df.to_dict(orient='records')
        cache.set(cache_key, records, timeout=60)  # 缓存 1 分钟
        return jsonify({'code': 0, 'data': records})
    except Exception as e:
        current_app.logger.error(f"[STOCK] get_b_minute error:\n{traceback.format_exc()}")
        return jsonify({'code': 500, 'msg': str(e)}), 500
    
    #  分时数据接口
@stock_controller.get('/kline')
def get_kline():
    """
    GET /stock/kline?symbol=sh900901&period=1
    返回该 A 股或指数分时数据，支持 period=1,5,15,30,60，adjust 可选 "", "qfq", "hfq"
    """
    symbol = request.args.get('symbol', '').strip()
    period = request.args.get('period', '1').strip()

    # 确保 symbol 带有 "sh" 前缀
    if not symbol.startswith('sh'):
        symbol = f"sh{symbol}"

    if not symbol:
        return jsonify({'code': 400, 'msg': 'symbol 参数必填'}), 400

    cache_key = f"stock_kline:{symbol}:{period}"
    data = cache.get(cache_key)
    if data:
        return jsonify({'code': 0, 'data': data})

    try:
        # 调用 akshare 接口
        df = ak.stock_zh_a_minute(symbol=symbol, period=period)
        # 为 ECharts 准备：把 "day" 列格式化成字符串
        df = df.rename(columns={'day': 'time'})
        records = df.to_dict(orient='records')
        cache.set(cache_key, records, timeout=60)  # 缓存 1 分钟
        return jsonify({'code': 0, 'data': records})
    except Exception as e:
        current_app.logger.error(f"[STOCK] get_kline error:\n{traceback.format_exc()}")
        return jsonify({'code': 500, 'msg': str(e)}), 500


@stock_controller.post('/buy')
def buy_stock():
    """
    POST /api/stock/buy
    购买股票
    请求参数：
    - userid: 用户ID
    - products_id: 股票代码
    - products_name: 股票名称
    - quantity: 购买数量
    - price: 当前价格
    -trade_time: 交易时间
    """
    try:
        data = request.json
        current_app.logger.debug(f"Request JSON: {data}")  # 打印请求的 JSON 数据
        userid = data.get('userid')
        if isinstance(userid, str):
            userid = int(userid)  # 如果 userid 是字符串，转换为整数

        products_id = data.get('products_id')
        products_name = data.get('products_name')
        quantity = data.get('quantity')
        price = data.get('price')

         

        if not all([userid, products_id, products_name, quantity, price]):
            return jsonify({'code': 1, 'msg': '缺少必要参数'}), 400

        # 设置交易时间为当前时间
        trade_time = datetime.now()
        # 计算交易金额
        trade_amount = quantity * price

        # 更新用户资产
        asset = UserAsset.query.filter_by(userid=userid, products_id=products_id).first()
        if asset:
            asset.quantity += quantity
        else:
            asset = UserAsset(
                userid=userid,
                products_id=products_id,
                products_name=products_name,
                type='股票',
                quantity=quantity,
                buy_price=price
            )
            db.session.add(asset)

        # 添加交易记录
        transaction = Transaction(
            userid=userid,
            products_id=products_id,
            products_name=products_name,
            type='股票',
            trade_type='买入',
            quantity=quantity,
            trade_time=trade_time,  # 使用当前时间
            trade_amount=trade_amount
        )
        db.session.add(transaction)
        ##
        behavior_stats = UserBehaviorStats.query.filter_by(user_id=userid).first()
        behavior_stats.total_transactions = UserBehaviorStats.total_transactions + 1
        behavior_stats.total_commission = UserBehaviorStats.total_commission + trade_amount
        ##
        db.session.commit()
        return jsonify({'code': 0, 'msg': '购买成功'}), 200
    except Exception as e:
        db.session.rollback()
        return jsonify({'code': 1, 'msg': f'购买失败: {str(e)}'}), 500
    

@stock_controller.post('/sell')
def sell_stock():
    """
    POST /api/stock/sell
    卖出股票
    请求参数：
    - userid: 用户ID
    - products_id: 股票代码
    - products_name: 股票名称
    - quantity: 卖出数量
    - price: 当前价格
    """
    try:
        data = request.json
        userid = data.get('userid')
        products_id = data.get('products_id')
        products_name = data.get('products_name')
        quantity = data.get('quantity')
        price = data.get('price')

        if not all([userid, products_id, products_name, quantity, price]):
            return jsonify({'code': 1, 'msg': '缺少必要参数'}), 400

        trade_time = datetime.now()  # 设置交易时间为当前时间
        # 检查用户资产是否足够
        asset = UserAsset.query.filter_by(userid=userid, products_id=products_id).first()
        if not asset or asset.quantity < quantity:
            return jsonify({'code': 1, 'msg': '持仓不足，无法卖出'}), 400

        # 计算交易金额
        trade_amount = quantity * price

        # 更新用户资产
        asset.quantity -= quantity
        if asset.quantity == 0:
            db.session.delete(asset)

        # 添加交易记录
        transaction = Transaction(
            userid=userid,
            products_id=products_id,
            products_name=products_name,
            type='股票',
            trade_type='售出',
            quantity=quantity,
            trade_amount=trade_amount,
            trade_time=trade_time
        )
        db.session.add(transaction)
        ##
        behavior_stats = UserBehaviorStats.query.filter_by(user_id=userid).first()
        behavior_stats.total_transactions = UserBehaviorStats.total_transactions + 1
        behavior_stats.total_commission = UserBehaviorStats.total_commission + trade_amount
        ##
        db.session.commit()
        return jsonify({'code': 0, 'msg': '卖出成功'}), 200
    except Exception as e:
        db.session.rollback()
        return jsonify({'code': 1, 'msg': f'卖出失败: {str(e)}'}), 500